Nginx平滑升级要停服务?姿势不对吧
我们都知道nginx进程可以通过信号来进行控制,通过对主进程PID传入以下几个信号,使nginx完成对应的操作,主进程PID通过nginx.pid文件获得,或通过ps命令查询
TERM,INT 立即关闭(停止)进程,不处理完进行中的任务
QUIT 正常关闭(停止)进程,处理完当前任务后关闭
HUP 关闭旧的子进程套接字监听,旧的子进程仍然处理在进行中的任务,处理 完成后关闭,重新读取配置文件,启动新的子进程处理新的请求
USR1 重新打开日志文件
USR2 平滑升级可执行文件
WINCH 正常关闭子进程
以上是对主进程的信号控制,虽然很少用到,但是子进程也可以通过信号来控制,支持INT、QUIT、USR1、WINCH四种信号
接着挨着看下,首先是关闭进程,看下两种不同关闭进程的区别(为了更直观,用动图的方式展示)
INT信号(动图)
QUIT信号(动图)
可以看到,INT信号,进程直接退出,中断正在处理的进程,而QUIT信号,则在处理完已有请求后才退出
HUP信号(动图)
HUP信号通常是做配置更新之后的操作,主进程会检查配置语法有效性,之后读取新的配置,启动新的子进程(worker进程),这里有个重要的地方,就是如果它检测语法有问题,或者用新的配置文件启动新的监听套接字的时候,如果启动失败,它会回滚更改,继续使用过旧的配置,所以这也是很多人说nginx reload之后,配置没有生效,这个是很大概率的,正常我们可以在启动前,通过nginx -t来检测配置语法,没有问题之后,再通过reload或HUP信号去重新加载配置
master进程在收到HUP信号后,旧的子进程(worker进程)不会再分配新的请求,关闭监听套接字,将现有的进程处理完毕后,退出
USR1信号(动图)
USR1信号主要是用来做日志切割或备份时用到,在logrotate中的nginx日志配置中就可以看到,实际使用的就是USR1信号,来发送到nginx.pid,在对日志重命名,备份、压缩之后,需要通过这个信号量来重新打开日志文件,并记录日志
USR2信号(动图)
USR2信号主要是用来做版本升级的,这个是要说的重点,网上文章都是编译完新的nginx可执行文件后,通过cp,将新的可执行文件覆盖旧的可执行文件,结果可想而知,肯定是覆盖不了的,提示文件忙,因为文件在被调用,无法覆盖,然后接着让干掉所有调用nginx的进程,这有点扯了,用nginx,就是因为nginx可以平滑升级(像某巧克力一样丝滑),你让我kill掉所有nginx进程
正确的姿势是,重命名旧的nginx进程(备份),将新的nginx进程放到nginx的sbin目录下(nginx文件原来的位置),之后,通过USR2信号来平滑升级
主进程接收到USR2信号后,将pid文件重命名为.oldbin后缀的文件,然后通过新的可执行文件启动新的master进程,注意,新的master进程是由旧的master进程启动的,可以通过上图的PID看,然后新的master进程再启动新的子进程(worker进程),这个时候,旧的worker进程和新的worker进程都继续接收请求,注意,旧的工作进程并不会终止工作,仍然继续处理请求,这个时候,需要手动发送WINCH信号到旧的主进程,当然你也可以一个一个发送WINCH信号到子进程(累死你),当旧的主进程收到WINCH信号后,发送消息给旧的子进程(worker进程),要求子进程正常关闭
之后,只有新的子进程(worker进程)处理请求,但是旧的主进程不会退出,仍然工作,因为新的nginx启动后可能不正常,所以旧的主进程仍然可以帮助你回滚
当你发现新的主进程,并没有按你预想的那样,你可以发送HUP信号到旧的主进程,旧的主进程会重新启动新的子进程(worker进程),然后通过QUIT信号将新的主进程关闭,这种是比较温和的处理方式
如果你新的nginx完全无法工作,或影响比较大,那你应该用TERM信号,发送给新的主进程,让它和子进程(worker进程)立即退出,然后旧的主进程,会自动启动它的子进程(worker进程),回滚到之前的nginx版本
WINCH信号
当升级完成,新的主进程稳定工作,通过QUIT信号,让旧的主进程退出,升级完毕!
当然,如果是用包管理工具升级,就没有这么繁琐了
.linux下watch命令,用于间歇性执行程序,巧用watch命令,可以动态监测命令执行结果,动态执行循环命令
.linux下ps命令中显示的wchan列,可以用来查看进程状态,也可以通过进程id在/proc/{$id}/wchan中查看
持续更新,欢迎扫码关注,敬请期待!
最热门的文章
温馨提示
如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我。